/* 由 ecpg 处理（回归模式） */
/* 这些包含文件由预处理器添加 */
#include <ecpglib.h>
#include <ecpgerrno.h>
#include <sqlca.h>
/* 自动包含部分结束 */
#define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y))

#line 1 "thread_implicit.pgc"
/*
 *	线程测试程序
 *	作者：Lee Kindness.
 */
#include <stdint.h>
#include <stdlib.h>
#include "ecpg_config.h"

#ifndef ENABLE_THREAD_SAFETY
int main(void)
{
	printf("No threading enabled.\n");
	return 0;
}
#else
#ifndef WIN32
#include <pthread.h>
#else
#include <windows.h>
#include <locale.h>
#endif


#line 1 "regression.h"






#line 24 "thread_implicit.pgc"


void *test_thread(void *fc_arg);

int nthreads   = 10;
int iterations = 20;

int main()
{
#ifndef WIN32
  pthread_t *fc_threads;
#else
  HANDLE *threads;
#endif
  intptr_t fc_n;
  /* 执行 SQL 结束声明部分 */
   
  
#line 40 "thread_implicit.pgc"
 int fc_l_rows ;
/*
 * 默认连接: con2
 * 非默认连接: con1
 *
 */
#line 41 "thread_implicit.pgc"


 /* 不要在回归测试中开启调试输出。线程按
  * 更多或更少的随机顺序执行 */
 /* ECPGdebug(1, stderr); */

  /* 设置 test_thread 表 */
  { ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , NULL, 0); }
#line 48 "thread_implicit.pgc"

  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table test_thread", ECPGt_EOIT, ECPGt_EORT);}
#line 49 "thread_implicit.pgc"
 /* DROP 可能失败 */
  { ECPGtrans(__LINE__, NULL, "commit");}
#line 50 "thread_implicit.pgc"

  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table test_thread ( tstamp timestamp not null default cast ( timeofday ( ) as timestamp ) , thread text not null , iteration integer not null , primary key ( thread , iteration ) )", ECPGt_EOIT, ECPGt_EORT);}
#line 55 "thread_implicit.pgc"

  { ECPGtrans(__LINE__, NULL, "commit");}
#line 56 "thread_implicit.pgc"

  { ECPGdisconnect(__LINE__, "CURRENT");}
#line 57 "thread_implicit.pgc"


  /* 创建并启动线程 */
  fc_threads = calloc(nthreads, sizeof(fc_threads[0]));
  if( fc_threads == NULL )
    {
      fprintf(stderr, "Cannot alloc memory\n");
      return 1;
    }
  for( fc_n = 0; fc_n < nthreads; fc_n++ )
    {
#ifndef WIN32
      pthread_create(&fc_threads[fc_n], NULL, test_thread, (void *) (fc_n + 1));
#else
      threads[n] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) (void (*) (void)) test_thread, (void *) (n+1), 0, NULL);
#endif
    }

  /* 等待线程完成 */
#ifndef WIN32
  for( fc_n = 0; fc_n < nthreads; fc_n++ )
    {
      pthread_join(fc_threads[fc_n], NULL);
    }
#else
  WaitForMultipleObjects(nthreads, threads, TRUE, INFINITE);
#endif
  free(fc_threads);

  /* 并检查结果 */
  { ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , NULL, 0); }
#line 87 "thread_implicit.pgc"

  { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select count ( * ) from test_thread", ECPGt_EOIT, 
	ECPGt_int,&(fc_l_rows),(long)1,(long)1,sizeof(int), 
	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 88 "thread_implicit.pgc"

  { ECPGtrans(__LINE__, NULL, "commit");}
#line 89 "thread_implicit.pgc"

  { ECPGdisconnect(__LINE__, "CURRENT");}
#line 90 "thread_implicit.pgc"

  if( fc_l_rows == (nthreads * iterations) )
    printf("Success.\n");
  else
    printf("ERROR: Failure - expecting %d rows, got %d.\n", nthreads * iterations, fc_l_rows);

  return 0;
}

void *test_thread(void *fc_arg)
{
  long fc_threadnum = (intptr_t) fc_arg;

  /* 执行 SQL 结束声明部分 */
    
   
  
#line 104 "thread_implicit.pgc"
 int fc_l_i ;
 
#line 105 "thread_implicit.pgc"
 char fc_l_connection [ 128 ] ;
/*
 * 默认连接: con2
 * 非默认连接: con1
 *
 */
#line 106 "thread_implicit.pgc"


  /* 构建连接名称并连接到数据库 */
#ifndef _MSC_VER
  snprintf(fc_l_connection, sizeof(fc_l_connection), "thread_%03ld", fc_threadnum);
#else
  _snprintf(l_connection, sizeof(l_connection), "thread_%03ld", threadnum);
#endif
  /* 执行 SQL 任何 SQL 错误 sqlprint ; */
#line 114 "thread_implicit.pgc"

  { ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , fc_l_connection, 0); 
#line 115 "thread_implicit.pgc"

if (sqlca.sqlcode < 0) sqlprint();}
#line 115 "thread_implicit.pgc"

  if( sqlca.sqlcode != 0 )
    {
      printf("%s: ERROR: cannot connect to database!\n", fc_l_connection);
      return NULL;
    }
  { ECPGtrans(__LINE__, NULL, "begin");
#line 121 "thread_implicit.pgc"

if (sqlca.sqlcode < 0) sqlprint();}
#line 121 "thread_implicit.pgc"


  /* 插入到 test_thread 表中 */
  for( fc_l_i = 1; fc_l_i <= iterations; fc_l_i++ )
    {
      { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into test_thread ( thread , iteration ) values ( $1  , $2  )", 
	ECPGt_char,(fc_l_connection),(long)128,(long)1,(128)*sizeof(char), 
	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
	ECPGt_int,&(fc_l_i),(long)1,(long)1,sizeof(int), 
	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
#line 126 "thread_implicit.pgc"

if (sqlca.sqlcode < 0) sqlprint();}
#line 126 "thread_implicit.pgc"

      if( sqlca.sqlcode != 0 )
	printf("%s: ERROR: insert failed!\n", fc_l_connection);
    }

  /* 全部完成 */
  { ECPGtrans(__LINE__, NULL, "commit");
#line 132 "thread_implicit.pgc"

if (sqlca.sqlcode < 0) sqlprint();}
#line 132 "thread_implicit.pgc"

  { ECPGdisconnect(__LINE__, fc_l_connection);
#line 133 "thread_implicit.pgc"

if (sqlca.sqlcode < 0) sqlprint();}
#line 133 "thread_implicit.pgc"

  return NULL;
}
#endif /* 启用线程安全 */
